package solved;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashSet;

/*
ID:		liluyan1
LANG:	JAVA
TASK:	cowtour
*/
public class cowtour {
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new FileReader("cowtour.in"));
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
				"cowtour.out")));
		new cowtour().solve(f, out);
		out.close();
		System.exit(0);
	}
	
	private final static int INF = 100000*300;
	
	private void solve(BufferedReader f, PrintWriter out) throws IOException {
		int N = read(f);
		Point[] loc = new Point[N];
		int[] a;
		String[] g = new String[N];
		
		for (int i=0; i<N; i++) {
			a = read(f, 2);
			loc[i] = new Point(a[0], a[1]);
		}
		
		for (int i=0; i<N; i++) {
			g[i] = f.readLine();
		}
		
		double[][] dist = new double[N][N];
		double[][] D = new double[N][N];
		for (int i=0; i<N; i++) {
			for (int j=0; j<N; j++) {
				dist[i][j] = loc[i].getDistance(loc[j]);
				D[i][j] = g[i].charAt(j)=='1'? dist[i][j] : INF;
			}
		}
		
		// Floyd-Marshall
		for (int k=0; k<N; k++) {
			for (int i=0; i<N; i++) {
				for (int j=0; j<N; j++) {
					D[i][j] = Math.min(D[i][j], D[i][k] + D[k][j]);
				}
			}
		}
		
		double max = 0;
		for (int i=0; i<N; i++) {
			for (int j=0; j<N; j++) {
				if (D[i][j] < INF) max = Math.max(max, D[i][j]);
			}
		}
		
		ArrayList<HashSet> sets = new ArrayList<HashSet>();
		for (int i=0; i<N; i++) {
			boolean found = false;
			for (HashSet set : sets) {
				if (set.contains(i)) found = true;
			}
			if (!found) {
				HashSet<Integer> set = new HashSet<Integer>();
				set.add(i);
				for (int j=0; j<N; j++) {
					if (D[i][j] < INF) set.add(j);
				}
				sets.add(set);
			}
		}
		
		double min = INF;
		for (int i=0; i<sets.size(); i++) {
			for (int j=i+1; j<sets.size(); j++) {
				min = Math.min(min, getMinMax(sets.get(i), sets.get(j), D, dist));
			}
		}
		
		out.println(String.format("%.6f", Math.max(min, max)));
	}
	
	private double getMinMax(HashSet<Integer> s1, HashSet<Integer> s2, double[][] D, double[][] dist) {
		double min = INF;
		for (int i : s1) {
			for (int j : s2) {
				double newMax = dist[i][j];
				
				for (int i2 : s1) {
					if (i == i2) continue;
					
					for (int j2 : s2) {
						if (j == j2) continue;
						newMax = Math.max(newMax, D[i2][i] + dist[i][j] + D[j][j2]);
					}
				}
				
				min = Math.min(min, newMax);
			}
		}
		return min;
	}
	
	private class Point {
		int x, y;
		public Point(int x, int y) {
			this.x = x;
			this.y = y;
		}
		
		public double getDistance(Point p) {
			return Math.sqrt((x-p.x)*(x-p.x) + (y-p.y)*(y-p.y));
		}
	}
	
	public int read(BufferedReader f) throws IOException {
		return Integer.parseInt(f.readLine());
	}
	
	public int[] read(BufferedReader f, int N) throws IOException {
		String[] t = f.readLine().split(" ");
		int[] a = new int[N];
		for (int i=0; i<N; i++) {
			a[i] = Integer.parseInt(t[i]);
		}
		return a;
	}
}
